home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-06-15 | 45.5 KB | 1,308 lines | [TEXT/MPS ] |
-
- /*
- File: SampleAgent.cp
-
- Contains: Sample Agent
-
- Copyright: © 1992-1992 by Apple Computer, Inc., all rights reserved.
-
- */
-
- /***************************************************************************************
-
- This sample agent provides an example of how to build an SNMP agent for the
- Macintosh. The SNMP Manager is a dynamically loaded shared library which runs under
- the Macintosh Shared Library Manager (S.L.M.). SNMP agents for the Macintosh
- must likewise be contained in shared libraries and must be written in c++.
-
- An agent can be pre-loaded automatically by the Shared Library Manager or it can be loaded
- on command by other code running either inside our outside of a shared library. This sample
- can be setup for either mode, see the SampleAgent.exp file. It can also be loaded
- and unloaded by the SNMPAgentTool.
-
- This agent "manages" a few simple variables and tables for demonstration purposes.
- Variables are registered with the SNMP Manager by means of variable objects. These
- variable objects are subclasses of the abstract class TSNMPVar found in the file
- SNMPVar.h. The TSNMPVar class has member functions for getting and setting the variable
- data. There are two examples of variable objects used in this agent - direct
- variables and indirect variables. Direct variables are given a size and pointer to the
- variable data, indirect variables are given addresses of get and set functions to be called
- when a get or a set is requested.
-
- When a packet is received requesting a set or get, the SNMP Manager will do the
- ASN.1 decoding. It will make a get or set request to the owning agent for each
- variable involved in the transaction. It will then handle the encoding and packetizing
- of the result. If a getnext call is made, the SNMP Manager will determine which
- variable needs to be retrieved and it will call the appropriate agent. The only time
- an agent will receive a getnext request is for a table element, in which case the
- agent must either return the value of that variable from the next row in the table,
- or return the end of column error.
-
- The SNMP Manager uses a three phase set when setting variables. This is of primary
- importance when creating new rows in a table. There are actually four phases described
- as follows:
-
- setAllocate: Allocate any memory required. Make sure there is space and if
- required, save information for consistency check phase.
-
- setConsistency: Check for consistency. This may involve checking that other
- variables are also getting set with proper values.
-
- setChange: Perform the set and make it permanent. This stage is not
- allowed to fail. Error checks must be made and errors reported
- during one of the earlier phases.
-
- setRevert: Either the setAllocate or the setConsistency failed for some
- variable being set in this transaction. Everything should be
- reverted to its previous state.
-
- ***************************************************************************************/
-
- #ifndef __TYPES__
- #include <Types.h>
- #endif
-
- #ifndef __RESOURCES__
- #include <Resources.h>
- #endif
-
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
-
- #ifndef __String__
- #include <String.h>
- #endif
-
- #ifndef __SNMP__
- #include "SNMP.h"
- #endif
-
- #ifndef __TSNMP__
- #include "TSNMP.h"
- #endif
-
- #ifndef __LIBRARYMANAGERUTILITIES__
- #include <LibraryManagerUtilities.h>
- #endif
-
- #ifndef __LIBRARYMANAGER__
- #include <LibraryManager.h>
- #endif
-
- #ifndef __LIBRARYMANAGERCLASSES__
- #include <LibraryManagerClasses.h>
- #endif
-
- #ifndef __STRINGS__
- #include <Strings.h>
- #endif
-
- #ifndef __SAMPLESNMPAGENT__
- #include "SampleAgent.h"
- #endif
-
- #ifndef __SAMPLEVAR__
- #include "SampleVar.h"
- #endif
-
- /**********************************************************************
- Variables and Constants
- **********************************************************************/
- /*
- Variable data
-
- The following variables represent the managed data that this sample agent
- manages. In a real world agent, these variables would be in the entity being
- managed, e.g. a router or server.
- */
-
- // storage for the direct variables
-
- long gDirIntRW = 100; // a direct read/write variable
-
- // storage for the indirect variables
-
- long gIndIntRW = 200; // an indirect read/write variable
- long gIndIntR = 300; // an indirect read only variable
-
- /*
- Table 1
- This table contains an integer and a string. This is a single index table where
- the SNMP index for the table is not a column within the table. The valid SNMP indexes for
- this table range from 1 to kT1MaxSize. There are three valid rows in the table to
- start with. The element T1Int determines whether or not a row is valid (exists). If this
- element contains zero, the row does not exist. If zero is written into it for an
- existing row, the row is in effect deleted. Just for kicks, the T1Int element will
- not allow its value to be greater than 1000.
- The element T1Str can contain any string, and will be set to all zeros by default
- if a new row is created (by setting T1Int to non-zero) without setting the T1Str field.
- */
-
- const short kT1MaxSize = 20; // size of the array to hold the table data
- const short kT1StrSize = 12; // size of TStr element
- const short kT1Elem_IDSize = 13; // size of base object id for this table - used to
- // retrieve the indexes off the object id
-
- long gT1Int[kT1MaxSize] = {1000, 2000, 3000};
- char gT1Str[kT1MaxSize][kT1StrSize] = {"t1 String 1", "t1 String 2", "t1 String 3"};
-
- long gT1IntTemp; // temp field to hold T1Int value for consistency check during set
- Boolean gT1IntSetFlag = false; // set flag for T1Int
-
- /* Table 2
- This table contains an integer, a string, 2 indexes, and a valid field. This is a 2 index
- table where the SNMP indexes are columns of the table. The valid SNMP indexes for
- this table range from 1 to kT2_MaxSize1 for index 1 and 1 to kT2MaxSize2 for index 2.
- There are nine valid rows in the table to start with. The Valid field of the table
- determines whether or not a row is valid (exists) and is used to create and delete
- rows.
- */
-
- const short kT2MaxSize1 = 10; // dimensions of the array which holds the table data
- const short kT2MaxSize2 = 10;
-
- const short kT2StrSize = 64; // size of string element
- const short kT2Elem_IDSize = 13; // size of base object id for this table - used to
- // retrieve the indexes off the object id
-
- // constants for T2Valid field
- const short kInvalid = 0;
- const short kValid = 1;
-
- long gT2Index1[kT2MaxSize1][kT2MaxSize2] = { {1, 1, 1}, {2, 2, 2}, {3, 3, 3} };
- long gT2Index2[kT2MaxSize1][kT2MaxSize2] = { {1, 2, 3}, {1, 2, 3}, {1, 2, 3} };
- char gT2Str[kT2MaxSize1][kT2MaxSize2][kT2StrSize] =
- {
- {"t2 String 1 1", "t2 String 1 2", "t2 String 1 3"},
- {"t2 String 2 1", "t2 String 2 2", "t2 String 2 3"},
- {"t2 String 3 1", "t2 String 3 2", "t2 String 3 3"}
- };
-
- long gT2Valid[kT2MaxSize1][kT2MaxSize2] =
- {
- {kValid, kValid, kValid},
- {kValid, kValid, kValid},
- {kValid, kValid, kValid}
- };
-
- // for consistency check
-
- Boolean gT2StrSetFlag = false;
- Boolean gT2ValidSetFlag = false;
- long gT2ValidTemp;
-
- /**********************************************************************
- Local Function Prototypes
- **********************************************************************/
-
- /*
- Callback function prototypes
-
- These are the callback functions used by the indirect variables for getting and
- setting the variable values.
- */
-
- static OSErr
- GetIndIntRW(Boolean next, ObjectIDPtr id, Ptr bufPtr, Size bufSize, Size *bufUsed);
-
- static OSErr
- SetIndIntRW(ObjectIDPtr id, Ptr bufPtr, Size bufSize, SetStage action);
-
- static OSErr
- GetIndIntR(Boolean next, ObjectIDPtr id, Ptr bufPtr, Size bufSize, Size *bufUsed);
-
- static OSErr
- GetT1Int(Boolean next, ObjectIDPtr id, Ptr bufPtr, Size bufSize, Size *bufUsed);
-
- static OSErr
- SetT1Int(ObjectIDPtr id, Ptr bufPtr, Size bufSize, SetStage action);
-
- static OSErr
- GetT1Str(Boolean next, ObjectIDPtr id, Ptr bufPtr, Size bufSize, Size *bufUsed);
-
- static OSErr
- SetT1Str(ObjectIDPtr id, Ptr bufPtr, Size bufSize, SetStage action);
-
- static OSErr
- GetT2Index1(Boolean next, ObjectIDPtr id, Ptr bufPtr, Size bufSize, Size *bufUsed);
-
- static OSErr
- GetT2Index2(Boolean next, ObjectIDPtr id, Ptr bufPtr, Size bufSize, Size *bufUsed);
-
- static OSErr
- GetT2Str(Boolean next, ObjectIDPtr id, Ptr bufPtr, Size bufSize, Size *bufUsed);
-
- static OSErr
- SetT2Str(ObjectIDPtr id, Ptr bufPtr, Size bufSize, SetStage action);
-
- static OSErr
- GetT2Valid(Boolean next, ObjectIDPtr id, Ptr bufPtr, Size bufSize, Size *bufUsed);
-
- static OSErr
- SetT2Valid(ObjectIDPtr id, Ptr bufPtr, Size bufSize, SetStage action);
-
- // other local functions
-
- void
- ClearCharArray(char array[], unsigned short size);
- // clear a char array
-
- OSErr
- FindT1Index(ObjectIDPtr id, Boolean next, Boolean forSet, unsigned short& theIndex);
- // Find the correct index for the table 1 array - extracts it from the object id.
- // Takes into account the setting of the next flag (getnext) and whether or not
- // a set is being performed.
-
- OSErr
- FindT2Index(ObjectIDPtr id, Boolean next, Boolean forSet, unsigned short& theIndex1,
- unsigned short& theIndex2);
- // Find the correct indexes for the table 1 array - extracts it from the object id.
- // Takes into account the setting of the next flag (getnext) and whether or not
- // a set is being performed.
-
-
- /*
- Callback Function and Variable Ptr Arrays
-
- These arrays contain pointers to the get and set callback functions, and for
- direct variables, the address of the variable storage. These arrays are used in
- conjunction with the Variable description resource to register the variables.
- The variable description resource contains all the information required to register
- the variables except (of course) these addresses. Each variable description
- in the resource contains an index into one of these arrays.
- */
-
- // callback functions for get
-
- GetVarProcPtr getProcArray[] = { GetIndIntRW,
- GetIndIntR,
- NULL,
- GetT1Int,
- GetT1Str,
- NULL,
- GetT2Index1,
- GetT2Index2,
- GetT2Str,
- GetT2Valid
- };
-
- // callback functions for set
-
- SetVarProcPtr setProcArray[] = { SetIndIntRW,
- NULL,
- NULL,
- SetT1Int,
- SetT1Str,
- NULL,
- NULL,
- NULL,
- SetT2Str,
- SetT2Valid
- };
-
- // address of direct variables
-
- void* varPtrArray[] = { &gDirIntRW
- };
-
- /*******************************************************************************
- Class Member Functions
-
- *******************************************************************************/
-
-
- /*******************************************************************************
- TSampleSNMPAgent Constructor
-
- This is where we construct ourselves and register both our agent and the
- variables we manage.
- *******************************************************************************/
- TSampleSNMPAgent::TSampleSNMPAgent()
- {
- OSErr result = noErr; // to hold result codes
- Str255 nameStr; // to hold strings retrieved from 'STR#' resource
- Str32 agentName; // var for getting agent name
- unsigned short i;
- short savedRefNum; // saved refnum for the library file object (used in Preflight & Postflight)
- Handle varRsrcHandle; // handle to hold the resource containing the variable data
- Handle nameRsrcHandle; // handle to hold the name string list resource
- TSampleSNMPAgent* anSNMPAgent; // used to verify that the agent doesn't already exist
-
- fValid = false; // set valid to false to start
- // this value is returned by the IsValid method
- // so that the "creator" can determine if the constructor
- // succedded or failed - since contructors cannot return
- // a result.
-
- fRegistered=false; // we have not registered this Agent yet
-
- if (!fSNMPManagerPtr) // is the SNMP Manager there ?
- return;
-
- // Lookup this object type with the Arbitrator.
- // First get the pointer to the Arbitrator
-
- TArbitrator* theArbitrator = GetGlobalArbitrator(); // get the global arbitrator
- anSNMPAgent = (TSampleSNMPAgent*)theArbitrator->LookupObject(kTSampleSNMPAgentID);
- if(anSNMPAgent) return; // Already created
-
- // Now we must get our variable description resource to get the information we need
- // to register our agent and variables. To get any resource in our library file,
- // we must first do a preflight to set it in the resource chain. When we are done
- // we must do a postflight on it to return things to their previous state.
-
- // First we must get our library file object
-
- fAgentLibraryPtr = GetLocalLibraryFile();
- if(!fAgentLibraryPtr) // is the library file there ?
- return;
-
- // Then we preflight it - saving the old RefNum for the postflight
- // when we're done.
-
- fAgentLibraryPtr->Preflight(savedRefNum);
-
- varRsrcHandle = Get1Resource(kVarRsrcType, kVarRsrcID); // get our var description resource
- if (!varRsrcHandle) // did it succeed
- {
- fAgentLibraryPtr->Postflight(savedRefNum); // do postflight
- return; // and get outa here !
- }
-
- // Here we are going to lock the resource because we will have pointers pointing into it.
-
- HLock(varRsrcHandle);
-
- VarDescRsrcPtr varResPtr = (VarDescRsrcPtr)(*varRsrcHandle); // de-reference the handle
-
- // Now we get our names STR# resource which contains our agent name and the
- // names of all our variables.
-
- nameRsrcHandle = Get1Resource('STR#', varResPtr->namesResID); // get the names resource
- if (!nameRsrcHandle)
- {
- ReleaseResource(varRsrcHandle);
- fAgentLibraryPtr->Postflight(savedRefNum); // do postflight
- return; // and get outa here !
- }
-
-
- // Get the agent name from the names resource using the index specified in the
- // variable description resource.
-
- GetIndString(agentName, varResPtr->namesResID, varResPtr->agentStrIndex);
-
- // Now we call our Init member function, passing the name of the agent and the
- // resource id and index for the description string.
-
- result = noErr;
-
- result = this->InitSNMPAgent(agentName, varResPtr->descResID, varResPtr->agentStrIndex, kOurVersion);
-
- if (!result)
- {
-
- // Now that we are all initializaed we need to Register this object
- // with the Arbitrator.
- // This registration should be done so that the Object can be found
-
- theArbitrator->RegisterObject(kTSampleSNMPAgentID, this); // register ourself
- fRegistered=true; // we have now registered this Agent
-
-
- // We set our count to the field in the variable description resource
- // which contains the count of the number of groups to register. Then we will set
- // our groupDataPtr to the first group data structure in the resource and begin
- // registering the groups - counting down the count as we go.
-
-
- short *countPtr = &varResPtr->groupCount; // find the count
- GroupRsrcPtr groupDataPtr = (GroupRsrcPtr)(countPtr + 1); // data for the first group
- for (i = 0; i < *countPtr; i++)
- {
- GetIndString(nameStr, varResPtr->namesResID, groupDataPtr->strIndex); // get the name
- if (result = fSNMPManagerPtr->AddGroup(this, &groupDataPtr->objID, nameStr, varResPtr->descResID,
- groupDataPtr->strIndex)) // add the group
- break;
- // now update the pointer to point to the next group in the resource
- groupDataPtr = (GroupRsrcPtr)(&groupDataPtr->objID.id[0] + groupDataPtr->objID.count);
- }
-
- // Now register the variables. We do essentially the same thing as with the groups.
- // We also get the index from the resource and retrieve the address of the variable
- // or the callback function from the appropriate array.
-
- if (!result)
- {
- TSampleIndirectVar *theIndirectVar;
- TSampleDirectVar *theDirectVar;
-
- countPtr = (short*)groupDataPtr; // point to the variable count
- VarRsrcPtr varDataPtr = (VarRsrcPtr)(countPtr + 1); // point to the variable data
-
- for (i = 0; i < *countPtr; i++)
- {
- GetIndString(nameStr, varResPtr->namesResID, varDataPtr->strIndex); // get the var name
- if (varDataPtr->varType == 0) // indirect variable?
- {
- if (!(theIndirectVar = new TSampleIndirectVar)) // make the var
- {
- result = -1;
- break;
- }
- if (result = theIndirectVar->InitSampleIndirectVar(this, &varDataPtr->objID, kMyPrecedence, varDataPtr->type,
- varDataPtr->access, varResPtr->descResID, varDataPtr->strIndex,
- getProcArray[varDataPtr->ptrIndex], setProcArray[varDataPtr->ptrIndex]))
- break;
- if (result = fSNMPManagerPtr->AddMIBVar(theIndirectVar, nameStr)) // register it
- break;
- }
- else
- {
- if (!(theDirectVar = new TSampleDirectVar)) // make the var
- {
- result = -1;
- break;
- }
- if (result = theDirectVar->InitSampleDirectVar(this, &varDataPtr->objID, kMyPrecedence,
- varDataPtr->type, varDataPtr->access, varResPtr->descResID, varDataPtr->strIndex,
- varPtrArray[varDataPtr->ptrIndex], varDataPtr->dataSize))
- break;
- if (result = fSNMPManagerPtr->AddMIBVar(theDirectVar, nameStr)) // register it
- break;
- }
-
- varDataPtr = (VarRsrcPtr)(&varDataPtr->objID.id[0] + varDataPtr->objID.count); // update the rsrc data ptr
- }
- }
- }
-
- // we're done - so finish up
-
- if (!result)
- result = fSNMPManagerPtr->RegisterDone(this); // we completed our registration
-
- ReleaseResource(nameRsrcHandle); // release the names resource
- ReleaseResource(varRsrcHandle); // release the var resource
- fAgentLibraryPtr->Postflight(savedRefNum); // postflight the library
- if (!result) // did we have a problem ?
- fValid = true; // set the valid flag - we succeeded
- }
-
- /*******************************************************************************
- TSampleSNMPAgent Destructor
-
- Our destructor. Called when we are deleted.
- *******************************************************************************/
- TSampleSNMPAgent::~TSampleSNMPAgent()
- {
- TArbitrator* theArbitrator;
- //
- // remove yourself from the Arbitrator
- //
- theArbitrator = GetGlobalArbitrator(); // get the global arbitrator
- if(fRegistered == true) theArbitrator->UnregisterObject(kTSampleSNMPAgentID);
- }
-
- /*******************************************************************************
- TSampleSNMPAgent::IsValid
-
- Returns the validity state of the agent. This provides a way for a creator
- determine if the constructor succeeded or failed.
- *******************************************************************************/
-
- Boolean TSampleSNMPAgent::IsValid() const
- {
- return fValid;
- }
-
-
-
- /*******************************************************************************
- Constructor & Destructor for the Sample Direct Variable
- *******************************************************************************/
- TSampleDirectVar::TSampleDirectVar()
- {
- }
-
- TSampleDirectVar::~TSampleDirectVar()
- {
- }
-
- /*******************************************************************************
- TSampleDirectVar::InitSNMPDirectVar
-
- Init for direct variables. Direct variables objects keep a ptr to the
- actual variable's address and a size. The direct variable object's
- member functions do the actual getting as setting.
- *******************************************************************************/
-
- OSErr TSampleDirectVar::InitSampleDirectVar(
- TSNMPAgent* agent, // unique identifier for the agent
- ObjectIDPtr id, // unique identifier of the variable
- short precedence, // lowest value gets responsibility
- ASNTagType type, // defines variable encoding
- SMIAccess access, // read/write, read-only, or no access
- short descResID, // resource id of description STR# resource
- short descStrIndex, // index of description string in STR# resource
- void* dataPtr,
- short dataSize)
- {
- fDataPtr = (char*)dataPtr; // save the addr of the var storage
- fDataSize = dataSize; // save the variable size
- return this->InitSNMPVar(agent, id, precedence, type, access, descResID, descStrIndex); // init our superclass
-
- }
-
- /*******************************************************************************
- TSampleDirectVar::GetVariable
-
- We do not have any tables which are handled as direct variables, so this
- member function should never get called with get next.
- *******************************************************************************/
-
- OSErr TSampleDirectVar::GetVariable(Boolean next,ObjectIDPtr, VarBuf* retBuf)
- {
- if (next) return snmpBadID;
-
- if (retBuf->maxlen < fDataSize) // is the buffer big enough ?
- return snmpBufTooSmall;
-
- for (short i = 0; i < fDataSize; i++) // copy the variable data to the buffer
- retBuf->buf[i] = fDataPtr[i];
- retBuf->len = fDataSize; // set the size being returned
- return snmpNoError;
- }
-
- /*******************************************************************************
- TSampleDirectVar::SetVariable
-
- Set a direct variable.
- *******************************************************************************/
-
- OSErr TSampleDirectVar::SetVariable(ObjectIDPtr, VarBuf* setBuf, SetStage action)
- {
-
- if (action == setAllocate)
- {
- if (setBuf->len > fDataSize)
- return snmpBufTooSmall;
- }
- else if(action == setChange) // only change it during the change phase of the set
- {
- ClearCharArray(fDataPtr, fDataSize); // clear the variable storage first
- for (short i = 0; i < setBuf->len; i++) // move the data
- fDataPtr[i] = setBuf->buf[i];
- }
- return snmpNoError;
- }
-
-
- /*******************************************************************************
- Constructor & Destructor for the Sample Direct Variable
- *******************************************************************************/
- TSampleIndirectVar::TSampleIndirectVar()
- {
- }
-
- TSampleIndirectVar::~TSampleIndirectVar()
- {
- }
-
-
- /*******************************************************************************
- TSampleIndirectVar::InitSNMPIndirectVar
-
- Init an indirect var object. Indirect vars use get and set callback
- functions for getting and setting the variable values.
- *******************************************************************************/
-
- OSErr TSampleIndirectVar::InitSampleIndirectVar(
- TSNMPAgent* agent, // unique identifier for the agent
- ObjectIDPtr id, // unique identifier of the variable
- short precedence, // lowest value gets responsibility
- ASNTagType type, // defines variable encoding
- SMIAccess access, // read/write, read-only, or no access
- short descResID, // resource id of description STR# resource
- short descStrIndex, // index of description string in STR# resource
- GetVarProcPtr getProc,
- SetVarProcPtr setProc)
- {
- fGetProc = getProc; // save the get and set function ptrs
- fSetProc = setProc;
- return this->InitSNMPVar(agent, id, precedence, type, access, descResID, descStrIndex); // init the superclass
- }
-
- /*******************************************************************************
- TSampleIndirectVar::GetVariable
-
- Get the value of an indirect variable. Just calls the get function
- which this variable was initialized with. The next parameter for the
- get function is set to indicate that whether this is a get or a getnext call.
- *******************************************************************************/
-
- OSErr TSampleIndirectVar::GetVariable(Boolean next,ObjectIDPtr theID, VarBuf* retBuf)
- {
- if (fGetProc)
- return fGetProc(next, theID, retBuf->buf, retBuf->maxlen, (Size *)&retBuf->len);
- else
- return snmpNoVarFound;
- }
-
- /*******************************************************************************
- TSampleIndirectVar::SetVariable
-
- Set the value of an indirect variable. Just calls the get function
- which this variable was initialized with.
- *******************************************************************************/
-
- OSErr TSampleIndirectVar::SetVariable(ObjectIDPtr theID, VarBuf* setBuf, SetStage action)
- {
- if (fSetProc)
- return fSetProc(theID, setBuf->buf, setBuf->len, action);
- else
- return snmpNoVarFound;
- }
-
-
- /*******************************************************************************
- Callback Functions
-
- The callback functions for setting and getting the indirect variables.
- *******************************************************************************/
-
- /*******************************************************************************
- GetIndIntRW
-
- This callback function will be called by the SNMP Manager to get the value
- of the variable gIndIntRW. We only need to make sure that the buffer is
- big enough, and then return the value and size along with the result code.
- *******************************************************************************/
- static OSErr
- GetIndIntRW(Boolean /* next */, ObjectIDPtr /* id */, Ptr bufPtr, Size bufSize, Size *bufUsed) {
-
- long *longPtr = (long*)bufPtr; // used to copy response to buf
- OSErr result;
-
- *bufUsed = 0; // set in case of error
-
- if (bufSize < sizeof(long)) // buffer big enough ?
- result = snmpBufTooSmall; // too bad!
- else
- {
- *longPtr = gIndIntRW; // put value in buffer
- *bufUsed = sizeof(long); // set the size used
- result = snmpNoError;
- }
-
- return result;
- }
-
- /*******************************************************************************
- SetIndIntRW
-
- This callback function will be called by the SNMP Manager to set the value
- of the variable gIndIntRW. We set the new value during the set stage of
- the three phase set.
- For setting of integer values, the SNMP Manager will always pass longs
- in the buffer, so there is not need for us to check the buffer size.
- *******************************************************************************/
- static OSErr
- SetIndIntRW(ObjectIDPtr , Ptr bufPtr, Size , SetStage action) {
-
- #pragma xunused (id,bufSize);
-
- long *longPtr = (long*)bufPtr; // used to copy response to buf
- OSErr result = snmpNoError; // result = no error unless otherwise changed
-
- if (action == setChange) // change stage - set it
- gIndIntRW = *longPtr;
-
- return result;
- }
-
-
- /*******************************************************************************
- GetIndIntR
-
- This functions is essentially the same as GetIndIntRW except that since this
- is a read only variable - there is no corresponding set function.
- *******************************************************************************/
- static OSErr
- GetIndIntR(Boolean , ObjectIDPtr , Ptr bufPtr, Size bufSize, Size *bufUsed) {
-
- #pragma xunused (next,id);
-
- long *longPtr = (long*)bufPtr; // used to copy response to buf
- OSErr result;
-
- *bufUsed = 0; // init in case of error
-
- if (bufSize < sizeof(long)) // buffer big enough ?
- result = snmpBufTooSmall;
- else
- {
- *longPtr = gIndIntR; // get the value
- *bufUsed = sizeof(long); // set the size used
- result = snmpNoError;
- }
-
- return result;
- }
-
-
- /*******************************************************************************
- GetT1Int
-
- Get the int element of table 1.
- *******************************************************************************/
- static OSErr
- GetT1Int(Boolean next, ObjectIDPtr id, Ptr bufPtr, Size bufSize, Size *bufUsed) {
-
- long *longPtr = (long*)bufPtr; // used to copy response to buf
- unsigned short theIndex = 0;
- OSErr result;
-
- *bufUsed = 0; // init in case of error
-
- if (bufSize < sizeof(long)) // buffer big enough ?
- result = snmpBufTooSmall;
-
- // get the correct array index to use
- else if ((result = FindT1Index(id, next, false, theIndex)) == snmpNoError)
- {
- *longPtr = gT1Int[theIndex]; // move the value
- *bufUsed = sizeof(long); // set the size used
-
- // Now set the returned object id correctly for the index that was used.
- // This is only required when a getnext is performed.
- // The field theIndex holds the index which was used for the array.
- // The object id indexes for this table start with 1, while the array index
- // is zero based - so we must add 1 to it.
- if (next)
- {
- id->count = kT1Elem_IDSize + 1; // set the count to the correct value
- // the base count plus 1 index
- id->id[kT1Elem_IDSize] = theIndex + 1; // set the index - it is 1 based
- }
- result = snmpNoError;
- }
-
- return result;
- }
-
- /*******************************************************************************
- SetT1Int
-
- Set the integer element of table 1. T1Int determines whether or not the
- row in the table is exists. If T1Int in the array is zero, the row is
- treated as non-existent. Also just for kicks, we do not allow the value
- of T1Int to be greater than 1000. Adding and deleting rows is accomplished
- by setting this element to the appropriate value.
- When this element is being set, we set a flag to indicate it and we place
- the value in a temp field so that if the other element of the table, T1Str,
- is being set, it can do a consistency check to make sure the row either
- exists and is not being deleted, or is being created.
- *******************************************************************************/
- static OSErr
- SetT1Int(ObjectIDPtr id, Ptr bufPtr, Size , SetStage action) {
-
- #pragma xunused (bufSize);
-
- long *longPtr = (long*)bufPtr; // used to copy response to buf
- unsigned short theIndex = 0;
- OSErr result = snmpNoError;
-
- // get the correct array index to use
- if ((result = FindT1Index(id, false, true, theIndex)) == snmpNoError)
- {
- // first the allocate stage - Here we must allocate any memory needed
- // or otherwise make sure there is space for the variable.
- if (action == setAllocate)
- {
- if (*longPtr < 0 || *longPtr > 1000) // check the value range
- result = snmpBadValue;
- else
- {
- gT1IntSetFlag = true; // for consistency check by T1Str
- gT1IntTemp = *longPtr; // save for consistency check by T1Str
- }
- }
- else if (action == setChange)
- {
- gT1Int[theIndex] = gT1IntTemp; // store the value
- gT1IntSetFlag = false; // clear the set flag
- if (gT1IntTemp == 0) // when deleting the row - set the default value for T1Str
- ClearCharArray(gT1Str[theIndex], kT1StrSize);
- }
- else if (action == setRevert) // if we're reverting:
- gT1IntSetFlag = 0; // clear the set flag
- }
-
- return result;
- }
-
- /*******************************************************************************
- GetT1Str
-
- Get the String element from table 1.
- *******************************************************************************/
- static OSErr
- GetT1Str(Boolean next, ObjectIDPtr id, Ptr bufPtr, Size bufSize, Size *bufUsed) {
-
- unsigned short theIndex;
- OSErr result;
- char* charPtr;
-
- *bufUsed = 0; // init in case of error
-
- if (bufSize < kT1StrSize) // buffer big enough ?
- result = snmpBufTooSmall;
-
- // get the correct array index to use
- else if ((result = FindT1Index(id, next, false, theIndex)) == snmpNoError)
- {
- charPtr = gT1Str[theIndex]; // get the address of the correct array element
-
- for (short i = 0; i < kT1StrSize; i++) // copy the data to the buffer
- bufPtr[i] = charPtr[i];
- *bufUsed = kT1StrSize; // set the bufUsed for return
-
- // Now set the returned object id correctly for the index that was used.
- // This is only required when a getnext is performed.
- // The field theIndex holds the index which was used for the array.
- // The object id indexes for this table start with 1, while the array index
- // is zero based - so we must add 1 to it.
- if (next)
- {
- id->count = kT1Elem_IDSize + 1; // set the count to the correct value
- // the base count plus 1 index
- id->id[kT1Elem_IDSize] = theIndex + 1; // set the index
- }
- result = snmpNoError;
- }
-
- return result;
- }
-
- /*******************************************************************************
- SetT1Str
-
- Set the string element of table 1. We have to make sure it is only being
- set for a valid (existing) row in the table or one that is being created
- in this transaction.
- *******************************************************************************/
- static OSErr
- SetT1Str(ObjectIDPtr id, Ptr bufPtr, Size bufSize, SetStage action) {
-
- unsigned short theIndex = 0;
- OSErr result = snmpNoError;
-
-
- // get the correct array index to use
- if ((result = FindT1Index(id, false, true, theIndex)) == snmpNoError)
- {
- // First the allocate stage - Here we must allocate any memory needed
- // or otherwise make sure there is space for the variable.
- if (action == setAllocate)
- {
- if (bufSize > kT1StrSize) // buffer big enough ?
- result = snmpBadValue;
- }
- // During the consistency stage we must make sure we are setting this value
- // in a row which either exists and is not being deleted, or one which is being
- // created.
- else if (action == setConsistency)
- {
- if ((gT1IntSetFlag && gT1IntTemp == 0) || (!gT1IntSetFlag && gT1Int[theIndex] == 0))
- result = snmpBadValue;
- }
- else if (action == setChange)
- {
- ClearCharArray(gT1Str[theIndex], kT1StrSize); // clear any old value
- for (short i = 0; i < bufSize; i++) // copy the data
- gT1Str[theIndex][i] = bufPtr[i];
- }
- }
-
- return result;
- }
-
-
- /*******************************************************************************
- GetT2Index1
-
- Get the index1 element from table 2.
- *******************************************************************************/
- static OSErr
- GetT2Index1(Boolean next, ObjectIDPtr id, Ptr bufPtr, Size bufSize, Size *bufUsed) {
-
- long *longPtr = (long*)bufPtr; // used to copy response to buf
- unsigned short theIndex1;
- unsigned short theIndex2;
- OSErr result;
-
- *bufUsed = 0; // init in case of error
-
- if (bufSize < sizeof(long)) // buffer big enough ?
- result = snmpBufTooSmall;
-
- // get the correct array indexes to use
- else if ((result = FindT2Index(id, next, false, theIndex1, theIndex2)) == snmpNoError) {
- *longPtr = gT2Index1[theIndex1][theIndex2]; // get the value
- *bufUsed = sizeof(long); // set the buffer size used
-
- // Now set the returned object id correctly for the indexes that were used.
- // This is only required when a getnext is performed.
- // The index fields hold the index values which were used for the array.
- // The object id indexes for this table start with 1, while the array indexes
- // are zero based - so we must add 1 to them.
- if (next)
- {
- id->count = kT2Elem_IDSize + 2; // set the count
- id->id[kT2Elem_IDSize] = theIndex1 + 1; // set the indexes - 1 based
- id->id[kT2Elem_IDSize + 1] = theIndex2 + 1;
- }
- result = snmpNoError;
- }
-
- return result;
- }
-
-
- /*******************************************************************************
- GetT2Index2
-
- Get the index2 element from table 2.
- *******************************************************************************/
- static OSErr
- GetT2Index2(Boolean next, ObjectIDPtr id, Ptr bufPtr, Size bufSize, Size *bufUsed) {
-
- long *longPtr = (long*)bufPtr; // used to copy response to buf
- unsigned short theIndex1;
- unsigned short theIndex2;
- OSErr result;
-
- *bufUsed = 0; // init in case of error
-
- if (bufSize < sizeof(long)) // buffer big enough ?
- result = snmpBufTooSmall;
-
- // get the correct array indexes to use
- else if ((result = FindT2Index(id, next, false, theIndex1, theIndex2)) == snmpNoError) {
- *longPtr = gT2Index2[theIndex1][theIndex2]; // get the value
- *bufUsed = sizeof(long); // set the buffer size used
-
- // Now set the returned object id correctly for the indexes that were used.
- // This is only required when a getnext is performed.
- // The index fields hold the index values which were used for the array.
- // The object id indexes for this table start with 1, while the array indexes
- // are zero based - so we must add 1 to them.
- if (next)
- {
- id->count = kT2Elem_IDSize + 2; // set the count
- id->id[kT2Elem_IDSize] = theIndex1 + 1; // set the indexes - 1 based
- id->id[kT2Elem_IDSize + 1] = theIndex2 + 1;
- }
- result = snmpNoError;
- }
-
- return result;
- }
-
- /*******************************************************************************
- GetT2Str
-
- Get the string element from table 2.
- *******************************************************************************/
- static OSErr
- GetT2Str(Boolean next, ObjectIDPtr id, Ptr bufPtr, Size bufSize, Size *bufUsed) {
-
- unsigned short theIndex1=0;
- unsigned short theIndex2=0;
- OSErr result;
- char* strPtr;
-
- strPtr = gT2Str[theIndex1][theIndex2];
-
- *bufUsed = 0; // init in case of error
-
- // get the correct array indexes to use - depending on whether or not
- // next was set
- if ((result = FindT2Index(id, next, false, theIndex1, theIndex2)) == snmpNoError)
- {
- strPtr = gT2Str[theIndex1][theIndex2]; // get ptr to the string
-
- if (bufSize < kT2StrSize) // buffer big enough ?
- result = snmpBufTooSmall;
- else
- {
- for (short i = 0; i < kT2StrSize; i++) // copy the string
- bufPtr[i] = strPtr[i];
- *bufUsed = kT2StrSize; // set the size used
-
- // now set the returned object id correctly for the indexes that were retrieved.
- // the object id indexes for this table start with 1 not 0 - so the
- // index values must be incremented by 1
- if (next)
- {
- id->count = kT2Elem_IDSize + 2; // set the count
- id->id[kT2Elem_IDSize] = theIndex1 + 1; // set the indexes - 1 based
- id->id[kT2Elem_IDSize + 1] = theIndex2 + 1;
- }
- result = snmpNoError;
- }
- }
-
- return result;
- }
-
- /*******************************************************************************
- SetT2Str
-
- Set the string element of table 2.
- *******************************************************************************/
- static OSErr
- SetT2Str(ObjectIDPtr id, Ptr bufPtr, Size bufSize, SetStage action) {
-
- unsigned short theIndex1 = 0;
- unsigned short theIndex2 = 0;
- OSErr result = snmpNoError;
-
-
- // get the correct array index to use
- if ((result = FindT2Index(id, false, true, theIndex1, theIndex2)) == snmpNoError)
- {
- // First the allocate stage - Here we must allocate any memory needed
- // or otherwise make sure there is space for the variable.
- if (action == setAllocate)
- {
- if (bufSize > kT2StrSize)
- result = snmpBadValue;
- }
- else if (action == setConsistency)
- {
- if ( (gT2ValidSetFlag && gT2ValidTemp == kInvalid) ||
- (!gT2ValidSetFlag && gT2Valid[theIndex1][theIndex2] == kInvalid) )
- result = snmpBadValue;
- }
- else if (action == setChange)
- {
- ClearCharArray(gT2Str[theIndex1][theIndex2], kT2StrSize);
- for (short i = 0; i < bufSize; i++)
- gT2Str[theIndex1][theIndex2][i] = bufPtr[i];
- }
- }
-
- return result;
- }
-
-
- /*******************************************************************************
- GetT2Valid
-
- Get the Valid element of table 2. This element determines if the row
- is valid (exists).
- *******************************************************************************/
- static OSErr
- GetT2Valid(Boolean next, ObjectIDPtr id, Ptr bufPtr, Size bufSize, Size *bufUsed) {
-
- long *longPtr = (long*)bufPtr; // used to copy response to buf
- unsigned short theIndex1;
- unsigned short theIndex2;
- OSErr result;
-
- *bufUsed = 0; // init in case of error
-
- if (bufSize < sizeof(long)) // buffer big enough ?
- result = snmpBufTooSmall;
-
- // get the correct array indexes to use - depending on whether or not
- // next was set
- else if ((result = FindT2Index(id, next, false, theIndex1, theIndex2)) == snmpNoError) {
- *longPtr = gT2Valid[theIndex1][theIndex2]; // get the value
- *bufUsed = sizeof(long); // set the buffer size used
-
- // Now set the returned object id correctly for the indexes that were used.
- // This is only required when a getnext is performed.
- // The index fields hold the index values which were used for the array.
- // The object id indexes for this table start with 1, while the array indexes
- // are zero based - so we must add 1 to them.
- if (next)
- {
- id->count = kT2Elem_IDSize + 2; // set the count
- id->id[kT2Elem_IDSize] = theIndex1 + 1; // set the indexes - 1 based
- id->id[kT2Elem_IDSize + 1] = theIndex2 + 1;
- }
- result = snmpNoError;
- }
-
- return result;
- }
-
- /*******************************************************************************
- SetT2Valid
-
- Set the Valid element of table 2.
- *******************************************************************************/
- static OSErr
- SetT2Valid(ObjectIDPtr id, Ptr bufPtr, Size bufSize, SetStage action) {
-
- long *longPtr = (long*)bufPtr;
- unsigned short theIndex1 = 0;
- unsigned short theIndex2 = 0;
- OSErr result = snmpNoError;
-
-
- // get the correct array index to use
- if ((result = FindT2Index(id, false, true, theIndex1, theIndex2)) == snmpNoError)
- {
- // First the allocate stage - Here we must allocate any memory needed
- // or otherwise make sure there is space for the variable.
- // We also set a flag and save the value being set so that if the T2Str element
- // of the table is being set, it can make a consistency check to be sure it is
- // being set in an existing row or in one that is being created.
- if (action == setAllocate)
- if (bufSize > sizeof(gT2Valid))
- result = snmpBadValue;
- else
- {
- gT2ValidSetFlag = true;
- gT2ValidTemp = *longPtr;
- }
- else if (action == setChange)
- {
- if (gT2ValidTemp == kInvalid) // if deleting row - set default value for T2Str
- ClearCharArray(gT2Str[theIndex1][theIndex2], kT2StrSize);
- gT2Valid[theIndex1][theIndex2] = gT2ValidTemp; // set the value
- gT2Index1[theIndex1][theIndex2] = theIndex1 + 1; // init/set the index1 element
- gT2Index2[theIndex1][theIndex2] = theIndex2 + 1; // init/set the index2 element
- gT2ValidSetFlag = false; // clear the set flag
- }
- else if (action == setRevert) // if we are reverting
- gT2ValidSetFlag = false; // clear the set flag
- }
-
- return result;
- }
-
- /*******************************************************************************
- ClearCharArray
-
- Clears a character array. Used to clear the string elements of the tables
- before moving data into them, since there is no guarantee that the strings
- will end in a null character. The string variables are just an array of
- bytes. And since, when setting them, we only move the number of bytes
- specified in the set call, we have to make sure the remaining bytes are
- cleared.
- *******************************************************************************/
-
- void
- ClearCharArray(char array[], unsigned short size)
- {
- for (short i = 0; i < size; i++)
- array[i] = 0;
- }
-
-
- /*******************************************************************************
- FindT1Index
-
- Determine the correct array index to use for the table 1 array. This
- determination is based on the object id passed and whether a get, getnext,
- or a set is being performed.
- *******************************************************************************/
- OSErr
- FindT1Index(ObjectIDPtr id, Boolean next, Boolean forSet, unsigned short& theIndex)
- {
- if (next)
- {
- // First find the starting index value.
- // If the count is less than the base id count - no indexes were specified
- // so start with 0 - otherwise we use the given index as the starting
- // point. We don't have to increment it to start with the next entry in the
- // array since the index is 1 based and the array is zero based.
-
- theIndex = (unsigned short)(id->count <= kT1Elem_IDSize ? 0 : id->id[kT1Elem_IDSize]);
-
- // Since we must be doing a get if the next parameter is set
- // we search for the next available value in the table.
- // If the starting index is out of bounds, this loop will do the right thing.
-
- for (theIndex = theIndex; theIndex < kT1MaxSize; theIndex++)
- if (gT1Int[theIndex])
- return snmpNoError;
- return snmpEndOfColumn;
- }
-
- // since this is not a next request - we check to see if the index is valid.
- // if the forSet flag is set we don't check to see if it points to a valid
- // entry in the array since this is for a set operation
- else if ( (id->count != kT1Elem_IDSize + 1) || // id count correct ?
- ((theIndex = (unsigned short)(id->id[kT1Elem_IDSize] - 1)) >= kT1MaxSize) || // index within range ?
- (theIndex < 0) ||
- (!forSet && !gT1Int[theIndex]) ) // if not set - is it a valid row ?
- return snmpBadID;
-
- return snmpNoError;
- }
-
-
- /*******************************************************************************
- FindT2Index
-
- Determine the correct array indexes to use for the table 2 array. This
- determination is based on the object id passed and whether a get, getnext,
- or a set is being performed.
- *******************************************************************************/
- OSErr
- FindT2Index(ObjectIDPtr id, Boolean next, Boolean forSet, unsigned short& theIndex1,
- unsigned short& theIndex2)
- {
-
- if (next)
- {
- // First find the starting index values.
- // If one or both of the indexes are missing from the id, the missing ones
- // are set to zero to start at the beginning of the array. Since the
- // indexes on the object id's are 1 based, and the arrays are zero based,
- // the first index must be decremented by 1 and the second index used
- // as is to start with the next entry in the array.
-
- theIndex1 = (unsigned short)(id->count < kT2Elem_IDSize + 1 ? 0 : id->id[kT2Elem_IDSize] - 1);
- theIndex2 = (unsigned short)(id->count < kT2Elem_IDSize + 2 ? 0 : id->id[kT2Elem_IDSize + 1]); // start with next
-
- // Since we must be doing a get if the next parameter is set
- // we search for the next available value in the table.
- // If either or both of the initial starting indexes were out of bounds
- // this while loop will do the right thing with it.
-
- while (theIndex1 < kT2MaxSize1)
- {
- while (theIndex2 < kT2MaxSize2)
- {
- if (gT2Valid[theIndex1][theIndex2])
- return snmpNoError;
- theIndex2++;
- }
- theIndex2 = 0;
- theIndex1++;
- }
-
- return snmpEndOfColumn;
- }
-
- // since this is not a next request - we check to see if the index is valid.
- // if the forSet flag is set we don't check to see if it points to a valid row.
- else if ( (id->count != kT2Elem_IDSize + 2) || // size correct ?
- ((theIndex1 = (unsigned short)(id->id[kT2Elem_IDSize] - 1)) >= kT2MaxSize1) || // within bounds ?
- (theIndex1 < 0) ||
- ((theIndex2 = (unsigned short)(id->id[kT2Elem_IDSize + 1] - 1)) >= kT2MaxSize2) ||
- (theIndex2 < 0) ||
- (!forSet && !gT2Valid[theIndex1][theIndex2]) ) // if set - valid row ?
- return snmpBadID;
-
- return snmpNoError;
- }
-